package com.xinQing.blogme.conf.security;

import com.fasterxml.jackson.core.JsonParseException;
import com.fasterxml.jackson.databind.JsonMappingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.xinQing.blogme.util.Check;
import com.xinQing.blogme.util.Response;
import com.xinQing.blogme.util.Result;
import lombok.Setter;
import lombok.extern.slf4j.Slf4j;
import org.springframework.http.HttpMethod;
import org.springframework.http.HttpStatus;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.BadCredentialsException;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.web.authentication.AbstractAuthenticationProcessingFilter;
import org.springframework.security.web.util.matcher.AntPathRequestMatcher;

import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

/**
 * 登录过滤
 *
 * Created by null on 2017/8/2.
 */
@Setter
@Slf4j
public class JWTLoginFilter extends AbstractAuthenticationProcessingFilter {

    private JWTTokenManager jwtTokenManager;

    public JWTLoginFilter(String url, AuthenticationManager authManager) {
        super(new AntPathRequestMatcher(url, HttpMethod.POST.name()));
        setAuthenticationManager(authManager);
    }

    @Override
    public Authentication attemptAuthentication(HttpServletRequest request, HttpServletResponse response) throws
            AuthenticationException, IOException, ServletException {
        if (!request.getContentType().startsWith("application/json")) {
            throw new BadCredentialsException("content-type必须为application/json");
        }
        JWTUser jwtUser = new JWTUser();
        try {
            jwtUser = new ObjectMapper().readValue(request.getInputStream(), JWTUser.class);
        } catch (JsonParseException | JsonMappingException e) {
            log.warn("{}", e);
        }
        if (Check.isEmpty(jwtUser.getUsername()) || Check.isEmpty(jwtUser.getPassword())) {
            throw new BadCredentialsException("username和password不能为空");
        }
        return getAuthenticationManager().authenticate(
                new UsernamePasswordAuthenticationToken(jwtUser.getUsername(), jwtUser.getPassword())
        );
    }

    @Override
    protected void successfulAuthentication(HttpServletRequest request, HttpServletResponse response, FilterChain chain,
                                            Authentication authResult) throws IOException, ServletException {
        jwtTokenManager.addAuthentication(response, authResult.getName());
    }

    @Override
    protected void unsuccessfulAuthentication(HttpServletRequest request, HttpServletResponse response,
                                              AuthenticationException e) throws IOException, ServletException {
        if (e instanceof AuthenticationException) {
            Response.writeJsonAndFlush(response,
                    Result.fail(HttpStatus.UNAUTHORIZED.value(), e.getMessage(), null));
        } else {
            Response.writeJsonAndFlush(response,
                    Result.fail(HttpStatus.UNAUTHORIZED.value(), "登录失败", null));
        }
    }
}
